#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <sys/epoll.h>

const static int MAX_EVENTS = 100;

int main()
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        perror("socket failed");
        return -1;
    }

    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(8080);

    int n = bind(listenfd, (struct sockaddr*)&addr, sizeof(addr));
    if (n < 0) {
        perror("bind failed");
        close(listenfd);
        return -2;
    }

    n = listen(listenfd, 8);
    if (n < 0) {
        perror("listen failed");
        close(listenfd);
        return -3;
    }

    // 1. 创建 epoll 实例
    int epollfd = epoll_create1(EPOLL_CLOEXEC);
    if (epollfd < 0) {
        perror("epoll_create failed");
        close(epollfd);
        close(listenfd);
        return -4;
    }

    // 2. 将 listenfd 添加进 epoll
    struct epoll_event ev;
    ev.data.fd = listenfd;
    ev.events = EPOLLIN; // LT

    n = epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);
    if (n < 0) {
        perror("epoll_ctl failed");
        close(epollfd);
        close(listenfd);
        return -5;
    }

    struct epoll_event events[MAX_EVENTS];
    char buffer[128] = {0};
    while (1) {
        // 3. 等待就绪事件
        int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);

        for (int i = 0; i < nfds; i++) {
            // 3.1 处理新连接
            if (events[i].data.fd == listenfd && (events[i].events & EPOLLIN)) {
                struct sockaddr peer;
                socklen_t len = sizeof(peer);
                bzero(&peer, len);

                int clientfd = accept(listenfd, (struct sockaddr*)&peer, &len);
                if (clientfd < 0) {
                    perror("accept failed");
                    break;
                }

                struct epoll_event new_ev;
                new_ev.data.fd = clientfd;
                new_ev.events = EPOLLIN; 

                int n = epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &new_ev);
                if (n < 0) {
                    perror("epoll_ctl failed");
                    close(clientfd);
                }
            }
            // 3.2 处理就绪客户端数据
            else {
                int clientfd = events[i].data.fd;

                int cnt = recv(clientfd, buffer, 128, 0);
                if (cnt < 0) {
                    perror("recv failed");
                    
                    epoll_ctl(epollfd, EPOLL_CTL_DEL, clientfd, NULL);
                    close(clientfd);
                }
                else if (cnt == 0) {
                    // 对端关闭
                    epoll_ctl(epollfd, EPOLL_CTL_DEL, clientfd, NULL);
                    close(clientfd);
                }
                else {
                    buffer[cnt] = 0;
                    printf("clientfd: %d, count: %d, buffer: %s\n", clientfd, cnt, buffer);

                    send(clientfd, buffer, cnt, 0);
                }
            }
        }
    }

    close(epollfd);
    close(listenfd);

    return 0;
}